home *** CD-ROM | disk | FTP | other *** search
- (******************************************************
- *
- * Donated to the Pascal/Z Users Group by Ithaca
- * Intersystems, Dec 1980.
- ******************************************************)
-
- Program xref; {$i+,e+,l- }
- { This is a quick and dirty program to do Pascal cross reference listings }
- { without regard to Pascal scoping rules. It has a minimum of comments and}
- { was intended for internal use only }
- { This program may die terribly if your program is not of correct Pascal }
- { syntax. Each symbol which only occurs once is marked with an '*'. }
- const tab = 9;
- cr = 13;
- lf = 10;
- blanks = ' ';
- symlen = 8;
- tabsize = 750;
- listsize = 10;
-
- type symbol = array[ 1..symlen ] of char;
- xreflist = record
- nextlist: ^xreflist;
- xreflines: array[ 1..listsize ] of integer;
- end;
- $string255 = string 255;
- $string0 = string 0;
- byte = 0..255;
-
- var i, j, linepos, symcnt: integer;
- caps,
- good_ctrl, { set of acceptable control characters }
- stop, stoppnum: set of char;
- tab_index: integer;
- entry: ^xreflist;
-
- { save all of the symbols in alphabetical order }
- symbols: array[ 1..tabsize ] of symbol;
-
- { for each symbol there is a list of references, this table has a }
- { pointer to the start of the list }
- xreftable: array[ 1..tabsize ] of ^xreflist;
-
- { count the number of references for the corresponding symbol }
- xctr: array[ 1..tabsize ] of integer;
-
- { it is important to know the line number in order to xref }
- linectr: integer;
-
- firstchar: boolean; { is this the first character on this line }
-
- answer: char;
-
- { used in reading the Pascal program }
- already_read: boolean;
- one_ahead,
- curch: char;
-
- { the latest symbol extracted from the Pascal program }
- current_symbol: array[ 1..symlen ] of char;
-
- { input/output files }
- pasprog,
- xrefout: text;
-
- { for constructing file names }
- filnam: string 50;
-
- { do a binary search for the current identifier, if found return the index }
- { and set the function return value to TRUE. }
- { if not found set index to correct insertion point. }
- function bsearch( var index: integer ): boolean;
- var i,j,k: integer;
- done: boolean;
- begin
- i := 1;
- j := symcnt;
- done := false;
- repeat
- k := (j - i + 1) div 2 + i;
- if current_symbol < symbols[ k ] then j := k - 1
- else if current_symbol > symbols[ k ] then i := k + 1
- else done := true
- until done or (i > j );
- index := k;
- if not done and (symbols[k] < current_symbol) then index := k + 1;
- bsearch := done
- end;
-
- { get the next character }
- { convert ugly control control characters to spaces and convert upper case }
- { to lower case }
- procedure nextch;
- begin
- if firstchar then linectr := linectr + 1;
- firstchar := eoln( pasprog );
- if already_read then begin
- curch := one_ahead;
- already_read := false
- end
- else if not eof( pasprog ) then begin
- read( pasprog, curch );
- { convert ugly control chars to spaces }
- if (curch < ' ') and not(curch in good_ctrl) then curch := ' ';
- { convert upper to lower case }
- if curch in caps then curch := chr( ord( curch ) + 32 );
- end;
- end;
-
- { return the look-a-head character from the input stream }
- function lookahead: char;
- var temp: char;
- begin
- if already_read then lookahead := one_ahead
- else begin
- temp := curch;
- nextch;
- one_ahead := curch;
- lookahead := curch;
- already_read := true;
- curch := temp
- end;
- end;
-
- { find the next symbol skipping over quoted strings, comments, numbers and }
- { special symbols (i.e. <> ) }
- procedure parse;
- var i: byte;
- begin
- { skip characters until we get one that can start an identifier or }
- { we hit the end of the file }
- repeat
- nextch;
- if curch = '''' then begin
- repeat
- nextch
- until curch = ''''
- end
- else if ((curch='(') and (lookahead='*')) or
- (curch = '{') then repeat
- repeat
- nextch
- until (curch = '*') or (curch='}')
- until (lookahead = ')') or (curch='}');
- until not (curch in stoppnum) or eof( pasprog );
- i := 0;
- current_symbol := blanks;
- { read the identifier into current_symbol, ignoring characters which }
- { exceed the maximum symbol length }
- repeat
- i := i + 1;
- if i <= symlen then current_symbol[ i ] := curch;
- nextch;
- until curch in stop;
- end;
-
- { add a cross reference entry to the table }
- procedure add_xref( sym_index, ref_line: integer );
- var ptrnum: integer;
- begin
- entry := xreftable[ sym_index ];
- ptrnum := xctr[sym_index] mod listsize + 1;
- xctr[sym_index] := xctr[sym_index]+1;
- while (entry^.nextlist <> nil) do entry := entry^.nextlist;
- if ptrnum = 1 then
- begin
- new( entry^.nextlist );
- entry := entry^.nextlist;
- entry^.nextlist := nil
- end;
- entry^.xreflines[ptrnum] := ref_line
- end;
-
-
- { add the current symbol to the symbol table at position 'index' }
- procedure add_symbol( index: integer );
- var i: integer;
- begin
- symcnt := symcnt + 1;
- for i := symcnt downto index+1 do begin
- symbols[ i ] := symbols[ i-1 ];
- xctr[ i ] := xctr[ i-1 ];
- xreftable[ i ] := xreftable[ i-1 ];
- end;
- new( entry );
- xctr[index] := 1;
- xreftable[index] := entry;
- entry^.nextlist := nil;
- entry^.xreflines[1] := linectr;
- symbols[index] := current_symbol
- end;
-
- { add an initial entry to the symbol table....these entries are the }
- { Pascal/Z reserved words. }
- procedure init( res: symbol );
- var i: integer;
- junk: boolean;
- begin
- current_symbol := res;
- junk := bsearch( i );
- add_symbol( i )
- end;
-
- function index( x, y: $string255 ): integer; external;
- procedure setlength( var x: $string0; y: integer ); external;
-
- {
- start of program
- }
- begin
- writeln( 'XREF -- version 1a' );
- already_read := false;
- good_ctrl := [ chr( tab ), chr( cr ), chr( lf ) ];
- stop := [ chr( tab ),' ',':',',','+','-','/','*','(',')','=','.','>',
- '<','{','}','[',']', '''', '^', ';' ];
- stoppnum := stop + [ '0'..'9' ];
- caps := [ 'A'..'Z' ];
- repeat
- if eoln( 0 ) then write( 'File name -- ' );
- readln( filnam );
- linepos := index( filnam, '.' );
- if linepos <> 0 then setlength( filnam, linepos-1 );
- append( filnam, '.pas' );
- reset( filnam, pasprog );
- until not eof( pasprog );
- for i := 1 to tabsize do symbols[ i ] := '} ';
- symcnt := 0;
- linectr := 0;
- firstchar := true;
- init( 'and ' );
- init( 'array ' );
- init( 'begin ' );
- init( 'case ' );
- init( 'const ' );
- init( 'div ' );
- init( 'do ' );
- init( 'downto ' );
- init( 'else ' );
- init( 'end ' );
- init( 'external' );
- init( 'file ' );
- init( 'for ' );
- init( 'forward ' );
- init( 'function' );
- init( 'goto ' );
- init( 'if ' );
- init( 'in ' );
- init( 'label ' );
- init( 'mod ' );
- init( 'nil ' );
- init( 'not ' );
- init( 'of ' );
- init( 'or ' );
- init( 'packed ' );
- init( 'procedur' );
- init( 'program ' );
- init( 'record ' );
- init( 'repeat ' );
- init( 'set ' );
- init( 'string ' );
- init( 'then ' );
- init( 'to ' );
- init( 'type ' );
- init( 'until ' );
- init( 'var ' );
- init( 'while ' );
- init( 'with ' );
- while not eof( pasprog ) do
- begin
- parse;
- if current_symbol <> blanks then begin
- if bsearch( tab_index ) then add_xref( tab_index, linectr )
- else add_symbol( tab_index )
- end;
- end;
- linepos := index( filnam, '.' );
- setlength( filnam, linepos-1 );
- append( filnam, '.xrf' );
- rewrite( filnam, xrefout );
- writeln( xrefout, 'Total identifiers = ', symcnt-38:1 );
- for j := 1 to symcnt do
- if xreftable[ j ]^.xreflines[ 1 ] <> 0 then begin
- writeln( xrefout, ' ' );
- write( xrefout, symbols[ j ], ' ' );
- entry := xreftable[ j ];
- for i := 1 to xctr[ j ] do
- begin
- write( xrefout,
- entry^.xreflines[(i-1) mod listsize + 1]:6 );
- if (i mod 10 = 0) and (xctr[ j ] > i ) then begin
- writeln( xrefout );
- write( xrefout, ' ' )
- end;
- if i mod listsize = 0 then entry := entry^.nextlist;
- end;
- if xctr[ j ] = 1 then write( xrefout, '*' );
- end;
- write( 'Include reserved words? ' ); readln( answer );
- if answer in [ 'Y', 'y' ] then begin
- writeln( xrefout );
- writeln( xrefout );
- writeln( xrefout, 'Reserved words:' );
- for j := 1 to symcnt do
- if xreftable[ j ]^.xreflines[ 1 ] = 0 then begin
- writeln( xrefout, ' ' );
- write( xrefout, symbols[ j ], ' ' );
- entry := xreftable[ j ];
- for i := 2 to xctr[ j ] do
- begin
- write( xrefout,
- entry^.xreflines[(i-1) mod listsize + 1]:6 );
- if (i mod 10 = 0) and (xctr[ j ] > i ) then begin
- writeln( xrefout );
- write( xrefout, ' ' )
- end;
- if i mod listsize = 0 then entry := entry^.nextlist;
- end;
- end;
- end;
- end.